from datetime import datetime, timedelta
from django.conf import settings
from django.contrib.auth.decorators import permission_required
from django.core.urlresolvers import reverse
from django.db import transaction
from django.http import Http404, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render_to_response
from django.template import RequestContext
from django.utils.translation import ugettext as _
from opinion_extractor.questionnaire.models import Questionnaire
from exceptions import UserTinkeredWithOpinionForm, OpinionFormTimedOut
import utils


@permission_required('questionnaire.answer_questionnaire')
@transaction.commit_on_success
def change(request, slug):
    timeout = timedelta(
        minutes=settings.OPINION_EXTRACTOR['max_minutes_for_opinion_change']
    )
    questionnaire = get_object_or_404(Questionnaire.published, slug=slug)
    user = request.user
    
    # Sanity check - the user must satisfy questionnaire.population_filter
    utils.get_latest_respondent_profile_for_questionnaire(user, questionnaire)
    
    meta_data_key = "opinion_change_%d_meta" % questionnaire.pk
    form_class = utils.get_opinion_form(user, questionnaire)
    if request.method == 'POST':
        form = form_class(request.POST)
        meta_data = request.session.get(meta_data_key)
        
        # Sanity check - Meta data must be present in session 
        if not meta_data:
            raise UserTinkeredWithOpinionForm(user, questionnaire)

        # Sanity check - Meta data should not timeout
        now = datetime.now()
        time_taken = now - meta_data['start_time']
        if time_taken > timeout:
            del request.session[meta_data_key]
            raise OpinionFormTimedOut(user, questionnaire)
        
        if form.is_valid():
            new_opinion = form.get_opinion()
            new_opinion.num_failled_attempts = meta_data['num_failled_attempts']
            new_opinion.responded_at_time = now.time()
            new_opinion.response_time_sec = time_taken.seconds
            new_opinion.save()
            
            del request.session[meta_data_key] # Meta data is no longer needed
            request.user.message_set.create(
                message=_("You have successfully given your opinion on the questionnaire '%(questionnaire)s'.") %
                {'questionnaire': questionnaire}
            )
            return HttpResponseRedirect(reverse('opinion_list'))
        else:
            meta_data['num_failled_attempts'] += 1
            request.session.modified = True
    else:
        form = form_class()
        if meta_data_key not in request.session:
            request.session[meta_data_key] = {
                'start_time': datetime.now(),
                'num_failled_attempts': 0
            }
    
    return render_to_response(
        'opinion/change.html',
        {
            'form': form,
            'questionnaire': questionnaire,
            'title': questionnaire.title
        },
        context_instance=RequestContext(request)
    )


@permission_required('questionnaire.answer_questionnaire')
def list(request):
    # TODO: Don't include questionnaires for which the user still can't change his opinion (too fast)
    return render_to_response(
        'opinion/list.html',
        {
            'questionnaires': utils.get_questionnaires_for_user(request.user),
            'title': _('Select the questionnaire you wish to participate in')
        },
        context_instance=RequestContext(request)
    )
